import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  HostBinding,
  Inject,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  SimpleChanges,
} from '@angular/core';
import { Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { AvtSelectDataService } from './avt-select-data.service';
import { SelectionModel } from '@angular/cdk/collections';

@Component({
  selector: 'avt-option-panel',
  template: `
    <div style="display: flex; padding: 0 5px">
      <input
        class="filter-input"
        placeholder="Please enter the filtering data"
        type="text"
        (input)="onInputfilter($event)"
        [(ngModel)]="filterString"
      />
    </div>

    <ng-container *ngIf="hasFilterOption$ | async; else empty">
      <avt-option
        *ngIf="mode === 'multi'"
        value="selectAll"
        mode="multi"
        [isChecked]="(isSelectedAll$ | async) || false"
        display="flex"
        (isCheckedChange)="selectAllChange($event)"
      >
        <span style="font-weight: bold;"> Select All </span>
      </avt-option>
      <cdk-virtual-scroll-viewport
        itemSize="26"
        [style]="{ height: 26 * 10 + 'px' }"
      >
        <avt-option
          *cdkVirtualFor="let opt of lsOptData | async"
          [value]="opt.__value"
          [mode]="mode"
          display="flex"
          [isChecked]="selectionMode.isSelected(opt)"
          (isCheckedChange)="checkedChange($event, opt)"
        >
          {{ opt.__label }}
        </avt-option>
      </cdk-virtual-scroll-viewport>
    </ng-container>
    <ng-template #empty> No Data </ng-template>
  `,
  styles: [
    `
      :host {
        display: inline-block;
        border: 1px solid #546e95;
        border-radius: 5px;
        background-color: #fff;
        padding: 4px 0;
      }
      :host > app-avt-option:first-of-type {
        border-bottom: 1px solid #ccc;
      }
      .filter-input {
        width: 100%;
        outline: none;
        height: 30px;
        border-radius: 3px;
        border: 1px solid #546e95;
      }
    `,
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AvtOptionPanelComponent implements OnInit, OnChanges, OnDestroy {
  selectionMode!: SelectionModel<any>;
  isSelectedAll$!: Observable<boolean>;
  searchInputFocus = true;
  mode!: 'single' | 'multi';
  lsOptData!: Observable<any[]>;
  hasFilterOption$!: Observable<boolean>;
  filterString: string = '';
  @HostBinding('style.width') @Input() width = '220px';

  constructor(
    private cdr: ChangeDetectorRef,
    @Inject(AvtSelectDataService) private dataSvc: AvtSelectDataService
  ) {}

  onInputfilter(ev: any) {
    this.dataSvc.filterString$.next(this.filterString);
  }

  ngOnInit() {
    const {
      selectionMode,
      mode,
      filterDataSource$,
      isSelectedAll$,
      destroy$,
      isExistOption$,
    } = this.dataSvc;
    this.lsOptData = filterDataSource$;
    this.selectionMode = selectionMode;
    this.isSelectedAll$ = isSelectedAll$;
    this.mode = mode;
    this.hasFilterOption$ = isExistOption$;
    this.dataSvc.singleClear$.pipe(takeUntil(destroy$)).subscribe(() => {
      this.cdr.markForCheck();
    });
  }
  selectAllChange(selectAll: any) {
    const { dataSource$ } = this.dataSvc;
    dataSource$.value.forEach((d) => {
      if (selectAll) {
        this.selectionMode.select(d);
      } else {
        this.selectionMode.deselect(d);
      }
    });
  }

  ngOnChanges(changes: SimpleChanges) {
    const { width } = changes;
    if (width) {
      this.width = width.currentValue + 'px';
    }
  }

  ngOnDestroy() {}

  checkedChange(isChecked: boolean, opt: any) {
    if (isChecked) {
      this.selectionMode.select(opt);
    } else {
      this.selectionMode.deselect(opt);
    }
    opt.isChecked = isChecked;
  }
}
